﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Drawing;

namespace App
{
    public class CBO : ComboBox
    {

        public const int WM_ERASEBKGND = 0x14;
        public const int WM_PAINT = 0xF;
        public const int WM_NC_PAINT = 0x85;
        public const int WM_PRINTCLIENT = 0x318;
        private static int DropDownButtonWidth = 17;

        [DllImport("user32.dll", EntryPoint = "SendMessageA")]
        public static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);

        [DllImport("user32")]
        public static extern IntPtr GetWindowDC(IntPtr hWnd);

        [DllImport("user32")]
        public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);


        static CBO()
        {
            DropDownButtonWidth = 20;

        }

        public CBO()
            : base()
        {
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.UpdateStyles();
        }

        protected override void OnSelectedValueChanged(EventArgs e)
        {
            base.OnSelectedValueChanged(e);
            this.Invalidate();
        }

        protected override void WndProc(ref Message m)
        {
            if (this.DropDownStyle == ComboBoxStyle.Simple)
            {
                base.WndProc(ref m);
                return;
            }

            IntPtr hDC = IntPtr.Zero;
            Graphics gdc = null;
            switch (m.Msg)
            {
                case WM_NC_PAINT:
                    hDC = GetWindowDC(this.Handle);
                    gdc = Graphics.FromHdc(hDC);
                    SendMessage(this.Handle, WM_ERASEBKGND, hDC.ToInt32(), 0);
                    SendPrintClientMsg();	// send to draw client area
                    PaintFlatControlBorder(this, gdc);
                    m.Result = (IntPtr)1;	// indicate msg has been processed			
                    ReleaseDC(m.HWnd, hDC);
                    gdc.Dispose();

                    break;
                case WM_PAINT:
                    base.WndProc(ref m);
                    // flatten the border area again
                    hDC = GetWindowDC(this.Handle);
                    gdc = Graphics.FromHdc(hDC);
                    Pen p = new Pen((this.Enabled ? BackColor : SystemColors.Control), 2);
                    if (this.Width > 3 && this.Height > 3)
                    {
                        gdc.DrawRectangle(p, new Rectangle(2, 2, this.Width - 3, this.Height - 3));
                    }

                    PaintFlatDropDown(this, gdc);
                    PaintFlatControlBorder(this, gdc);
                    ReleaseDC(m.HWnd, hDC);
                    gdc.Dispose();

                    break;
                default:
                    base.WndProc(ref m);
                    break;
            }
        }
        private void SendPrintClientMsg()
        {
            // We send this message for the control to redraw the client area
            Graphics gClient = this.CreateGraphics();
            IntPtr ptrClientDC = gClient.GetHdc();
            SendMessage(this.Handle, WM_PRINTCLIENT, ptrClientDC.ToInt32(), 0);
            gClient.ReleaseHdc(ptrClientDC);
            gClient.Dispose();
        }

        private void PaintFlatControlBorder(Control ctrl, Graphics g)
        {
            if (ctrl.Width <= 0) return;
            Rectangle rect = new Rectangle(0, 0, ctrl.Width, ctrl.Height);
            if (ctrl.Focused == false || ctrl.Enabled == false)
                ControlPaint.DrawBorder(g, rect, Color.FromArgb(141, 178, 227), ButtonBorderStyle.Solid);
            else
                ControlPaint.DrawBorder(g, rect, Color.FromArgb(147, 157, 9), ButtonBorderStyle.Solid);
        }
        private void PaintFlatDropDown(Control ctrl, Graphics g)
        {
            //if (DesignMode) return;
            if (ctrl.Width <= 0) return;
            if (ctrl.Width < DropDownButtonWidth) return;

            Rectangle rect = new Rectangle(ctrl.Width - DropDownButtonWidth, 0, DropDownButtonWidth, ctrl.Height);
            //ControlPaint.DrawComboButton(g, rect, ButtonState.Flat);
            g.FillRectangle(Brushes.White, rect);
            int len = 6;
            int x = ctrl.Width - 6;
            int y = ctrl.Height / 2 - 2;
            if (x <= 6 || y <= 1) return;
            Point[] pntArr = new Point[3];
            pntArr[0] = new Point(x, y);
            pntArr[1] = new Point(x - len, y);
            pntArr[2] = new Point(x - len / 2, (int)(len * Math.Sqrt(3) / 2 + y - 2));
            System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
            path.AddLines(pntArr);
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.FillPath(Brushes.Black, path);
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default;
            path.Dispose();
        }

        protected override void OnLostFocus(System.EventArgs e)
        {
            base.OnLostFocus(e);
            this.Invalidate();
        }

        protected override void OnGotFocus(System.EventArgs e)
        {
            base.OnGotFocus(e);
            this.Invalidate();
        }
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            this.Invalidate();
        }


    }
}
